In [1]:
# Código do modelo matemático - Desafio Bootcamp - Enacom
# Autoria: Cassiano Tavares
In [2]:
# Verificação se todas as bibliotecas necessárias estão instaladas. Caso contrário, ~\
# esta célula irá realizar a instalação das bibliotecas ainda nao instaladas

import pip

def import_or_install(pac):
    try:
        __import__(pac)
    except ImportError:
        pip.main(['install', pac])    

bibliotecas = ["tkinter", "pandas", "numpy", "math", "datetime","io","pyomo","re","collections","plotly.express","plotly.graph_objects"]


for b in bibliotecas:
    import_or_install(b)

print("Bibliotecas instaladas")
Bibliotecas instaladas
In [3]:
# Carrega as bibliotecas do Python
from tkinter import E
import pandas as pd
import numpy as np
import math
#from google.colab import files
import datetime
import io
import pyomo.environ as pyo
from pyomo.environ import *
from pyomo.opt import SolverFactory
import re
import sys                             
from collections import defaultdict
import plotly.express as px
import plotly.graph_objects as go
In [4]:
# Define o arquivo com dados de entrada
nome_input = 'dados_desafio_2023.xlsx'
In [5]:
# Lê os dados de entrada como data frames

# Carteira de Investimentos (IGNORA LINHAS COM CÉLULAS EM BRANCO)
df_carteira_investimentos  = pd.read_excel(nome_input, sheet_name='MASTER_40').dropna()

print(df_carteira_investimentos)
    Opção                                          Descrição  \
0       1                       MASTER 5500 D - PADRÃO - BRA   
1       2    MASTER 5500 D C/ ESTEIRA PRECISA - PADRÃO - BRA   
2       3  MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15...   
3       4       MASTER 5500 D C/ DIRECIONADOR - PADRÃO - BRA   
4       5                       MASTER 7500 D - PADRÃO - BRA   
5       6    MASTER 7500 D C/ ESTEIRA PRECISA - PADRÃO - BRA   
6       7         MASTER 7500 D C/ PNEU 11L15 - PADRÃO - BRA   
7       8  MASTER 7500 D C/ ESTEIRA PRECISA C/ PNEU 11L15...   
8       9                       MASTER 2500 D - PADRÃO - BRA   
9      10    MASTER 2500 D C/ ESTEIRA PRECISA - PADRÃO - BRA   
10     11  MASTER 2500 D CAFEEIRA C/ ESTEIRA PRECISA - PA...   
11     12  MASTER 2500 D CAFEEIRA C/ ESTEIRA PRECISA C/ D...   
12     13                     MASTER 5500 D - VERMELHO - BRA   
13     14                        MASTER 5500 D - VERDE - BRA   
14     15                      MASTER 5500 D - AMARELO - BRA   
15     16                         MASTER 5500 D - AZUL - BRA   
16     17  MASTER 5500 D C/ ESTEIRA PRECISA - VERMELHO - BRA   
17     18     MASTER 5500 D C/ ESTEIRA PRECISA - VERDE - BRA   
18     19   MASTER 5500 D C/ ESTEIRA PRECISA - AMARELO - BRA   
19     20      MASTER 5500 D C/ ESTEIRA PRECISA - AZUL - BRA   
20     21  MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15...   
21     22  MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15...   
22     23  MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15...   
23     24  MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15...   
24     25     MASTER 5500 D C/ DIRECIONADOR - VERMELHO - BRA   
25     26        MASTER 5500 D C/ DIRECIONADOR - VERDE - BRA   
26     27      MASTER 5500 D C/ DIRECIONADOR - AMARELO - BRA   
27     28         MASTER 5500 D C/ DIRECIONADOR - AZUL - BRA   
28     29                     MASTER 7500 D - VERMELHO - BRA   
29     30                        MASTER 7500 D - VERDE - BRA   
30     31                      MASTER 7500 D - AMARELO - BRA   
31     32                         MASTER 7500 D - AZUL - BRA   
32     33  MASTER 7500 D C/ ESTEIRA PRECISA - VERMELHO - BRA   
33     34     MASTER 7500 D C/ ESTEIRA PRECISA - VERDE - BRA   
34     35   MASTER 7500 D C/ ESTEIRA PRECISA - AMARELO - BRA   
35     36      MASTER 7500 D C/ ESTEIRA PRECISA - AZUL - BRA   
36     37       MASTER 7500 D C/ PNEU 11L15 - VERMELHO - BRA   
37     38          MASTER 7500 D C/ PNEU 11L15 - VERDE - BRA   
38     39        MASTER 7500 D C/ PNEU 11L15 - AMARELO - BRA   
39     40           MASTER 7500 D C/ PNEU 11L15 - AZUL - BRA   

    Custo do investimento (R$)  Retorno esperado (R$)  
0                         9706                  22804  
1                        16791                  15932  
2                        12953                  20329  
3                        10264                  29465  
4                        14240                  21801  
5                        13063                  32694  
6                        14314                  32016  
7                        15599                  17799  
8                        15073                  25006  
9                        16920                  32458  
10                       16617                  21419  
11                        9649                  22287  
12                       13997                  24908  
13                       14180                  27160  
14                       10317                  16648  
15                       13106                  31571  
16                       14531                  26113  
17                       13828                  18250  
18                       14556                  16982  
19                        9084                  22599  
20                       11382                  24161  
21                       11728                  18533  
22                       11144                  33029  
23                       16558                  16528  
24                       16014                  24586  
25                        9500                  15061  
26                       11706                  33897  
27                       12893                  22713  
28                       12210                  15630  
29                       14636                  32881  
30                       13256                  34890  
31                       16708                  28002  
32                       14881                  18796  
33                       12066                  17861  
34                       14448                  33380  
35                       15126                  29959  
36                       16814                  25048  
37                       15835                  19950  
38                       14239                  34103  
39                       14647                  28654  
In [6]:
# Criação dos conjuntos


# Criação do conjunto de opções invenstimentos
dict_I = dict(enumerate(df_carteira_investimentos["Opção"]))
print("Este é o conjunto de opções investimentos")
print(dict_I)
Este é o conjunto de opções investimentos
{0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10, 10: 11, 11: 12, 12: 13, 13: 14, 14: 15, 15: 16, 16: 17, 17: 18, 18: 19, 19: 20, 20: 21, 21: 22, 22: 23, 23: 24, 24: 25, 25: 26, 26: 27, 27: 28, 28: 29, 29: 30, 30: 31, 31: 32, 32: 33, 33: 34, 34: 35, 35: 36, 36: 37, 37: 38, 38: 39, 39: 40}
In [7]:
#Criação do parâmetro c_{i} - Custo de investimento do projeto


# Inicializa a matriz com zeros
c_i = [0 for e in dict_I.keys()]

# Preenche as posições de acordo com df_carteira_investimentos
for linha in df_carteira_investimentos.iterrows():
    
    # Extrai o conteúdo da linha atual
    dados_linha = list(linha[1])
    #print(dados_linha)


    # Define o índice do projeto de investimento
    try:
        # Procura o índice na lista do projeto de investimento
        i = list(dict_I.keys())[list(dict_I.values()).index(dados_linha[0])]  
        c_i[i]= dados_linha[2]        
    except:   
        # Projeto de investimento não encontrado
        i = -1


print(c_i)
[9706, 16791, 12953, 10264, 14240, 13063, 14314, 15599, 15073, 16920, 16617, 9649, 13997, 14180, 10317, 13106, 14531, 13828, 14556, 9084, 11382, 11728, 11144, 16558, 16014, 9500, 11706, 12893, 12210, 14636, 13256, 16708, 14881, 12066, 14448, 15126, 16814, 15835, 14239, 14647]
In [8]:
#Criação do parâmetro vpl_{i} - VPL do projeto


# Inicializa a matriz com zeros
vpl_i = [0 for e in dict_I.keys()]

# Preenche as posições de acordo com df_carteira_investimentos
for linha in df_carteira_investimentos.iterrows():
    
    # Extrai o conteúdo da linha atual
    dados_linha = list(linha[1])
    #print(dados_linha)


    # Define o índice do projeto de investimento
    try:
        # Procura o índice na lista do projeto de investimento
        i = list(dict_I.keys())[list(dict_I.values()).index(dados_linha[0])]  
        vpl_i[i]= dados_linha[3]        
    except:   
        # Projeto de investimento não encontrado
        i = -1


print(vpl_i)
[22804, 15932, 20329, 29465, 21801, 32694, 32016, 17799, 25006, 32458, 21419, 22287, 24908, 27160, 16648, 31571, 26113, 18250, 16982, 22599, 24161, 18533, 33029, 16528, 24586, 15061, 33897, 22713, 15630, 32881, 34890, 28002, 18796, 17861, 33380, 29959, 25048, 19950, 34103, 28654]
In [9]:
# Budget disponível para investimento
M = 300000
In [10]:
# Contra parte robusta

#Parâmetro zeta que define o nível de incerteza
zeta = 0.15

# Parâmetro gamma que definide o budget de incerteza
gamma = len(dict_I.keys())
In [11]:
# Criacao do modelo de otimização
model = pyo.ConcreteModel()


#Criação dos conjuntos do modelo de otimização

# Conjunto de opções invenstimentos
model.set_I = pyo.Set(initialize = dict_I.keys())
print("Este é o model.set_I")
print(dict_I.keys())
Este é o model.set_I
dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39])
In [12]:
#Criação da variável de decisão


# Variaáel de decisão: 1 se o projeto de investimento é selecionado
model.Y = pyo.Var(model.set_I, within=Binary)
Y = model.Y 
In [13]:
# Criação das variáveis de incerteza

# Variável dual do domínio da restrição do budget de incerteza
model.Lambda = pyo.Var(within=NonNegativeReals)
Lambda = model.Lambda


# Variável dual do domínio da restrição do domínio de zeta
model.Mu = pyo.Var(model.set_I, within=NonNegativeReals)
Mu = model.Mu
In [14]:
# Função objetivo do modelo
model.exprobj = pyo.Expression()

#Primeiro termo da Função Objetivo: Cálculo do VPL de todos os projetos
obj1 = sum(vpl_i[i]*Y[i] for i in model.set_I) 

#Segundo termo da Função Objetivo: Contraparte Robusta
obj2 = gamma*Lambda


# Função objetivo: 
model.exprobj =  obj1 - obj2

model.obj = pyo.Objective(expr= model.exprobj, sense = pyo.maximize)
In [15]:
#Restrições 02: Mochila

model.C2 = pyo.ConstraintList()
model.C2.add(expr=sum(Y[i]*c_i[i] for i in model.set_I) <= M)
Out[15]:
<pyomo.core.base.constraint._GeneralConstraintData at 0xd35d1832e0>
In [16]:
#Restrições 03: Se o investimento 1 for selecionado, então o investimento 5 não deve ser

model.C3a = pyo.ConstraintList()
model.C3a.add(expr = Y[0] <= M*(1-Y[4]))

model.C3b= pyo.ConstraintList()
model.C3b.add(expr = Y[4] <= M*(Y[1]))
Out[16]:
<pyomo.core.base.constraint._GeneralConstraintData at 0xd35d0eeca0>
In [17]:
#Restrições 04: Se o investimento 2 for selecionado, então o investimento 4 também deve ser.

model.C4 = pyo.ConstraintList()
model.C4.add(expr = Y[1] <= Y[3])
Out[17]:
<pyomo.core.base.constraint._GeneralConstraintData at 0xd35d0eed00>
In [18]:
#Restrições 05: Contraparte robusta

model.C5 =  pyo.ConstraintList()
for i in model.set_I:
    model.C5.add(expr = Lambda + Mu[i] >= c_i[i] * Y[i])
In [19]:
#Restrições 06 e 07: Domínio das variáveis de incerteza

model.C6 = pyo.ConstraintList()
model.C7 = pyo.ConstraintList()

for i in model.set_I:
    model.C6.add(expr=Lambda >= 0)
    model.C7.add(expr=Mu[i] >= 0)
In [20]:
# Restrições 08: Domínio da variável de decisão

model.C8 = pyo.ConstraintList()
for i in model.set_I:
    model.C8.add(expr=Y[i] >= 0)
In [21]:
# Escreve modelo em arquivo no formato LP
model.write('model.lp', io_options={'symbolic_solver_labels': True})

# Seleciona o solver

solver = pyo.SolverFactory('glpk')

solution = solver.solve(model, tee=True)

from pyomo.opt import SolverStatus, TerminationCondition

if (solution.solver.status == SolverStatus.ok) and (solution.solver.termination_condition == TerminationCondition.optimal):
    print("Solution is feasible and optimal")
    print("Objective function value = ", model.obj())

elif solution.solver.termination_condition == TerminationCondition.infeasible:
    print ("Failed to find solution.")
else:
    # something else is wrong
    print(str(solution.solver))
GLPSOL--GLPK LP/MIP Solver 5.0
Parameter(s) specified in the command line:
 --write C:\Users\CASSIA~1\AppData\Local\Temp\tmpb6ikms_5.glpk.raw --wglp
 C:\Users\CASSIA~1\AppData\Local\Temp\tmper_umsvq.glpk.glp --cpxlp C:\Users\CASSIA~1\AppData\Local\Temp\tmpr14sq5j2.pyomo.lp
Reading problem data from 'C:\Users\CASSIA~1\AppData\Local\Temp\tmpr14sq5j2.pyomo.lp'...
C:\Users\CASSIA~1\AppData\Local\Temp\tmpr14sq5j2.pyomo.lp:913: warning: lower bound of variable 'x1' redefined
C:\Users\CASSIA~1\AppData\Local\Temp\tmpr14sq5j2.pyomo.lp:913: warning: upper bound of variable 'x1' redefined
165 rows, 82 columns, 287 non-zeros
40 integer variables, all of which are binary
953 lines were read
Writing problem data to 'C:\Users\CASSIA~1\AppData\Local\Temp\tmper_umsvq.glpk.glp'...
785 lines were written
GLPK Integer Optimizer 5.0
165 rows, 82 columns, 287 non-zeros
40 integer variables, all of which are binary
Preprocessing...
2 hidden packing inequaliti(es) were detected
44 rows, 81 columns, 166 non-zeros
40 integer variables, all of which are binary
Scaling...
 A: min|aij| =  1.000e+00  max|aij| =  1.692e+04  ratio =  1.692e+04
GM: min|aij| =  8.613e-01  max|aij| =  1.161e+00  ratio =  1.348e+00
EQ: min|aij| =  7.615e-01  max|aij| =  1.000e+00  ratio =  1.313e+00
2N: min|aij| =  5.000e-01  max|aij| =  1.109e+00  ratio =  2.218e+00
Constructing initial basis...
Size of triangular part is 44
Solving LP relaxation...
GLPK Simplex Optimizer 5.0
44 rows, 81 columns, 166 non-zeros
*     0: obj =  -0.000000000e+00 inf =   0.000e+00 (40)
*    71: obj =   6.579945809e+05 inf =   0.000e+00 (0)
OPTIMAL LP SOLUTION FOUND
Integer optimization begins...
Long-step dual simplex will be used
+    71: mip =     not found yet <=              +inf        (1; 0)
+    94: >>>>>   6.317210000e+05 <=   6.574957348e+05   4.1% (23; 0)
+   184: >>>>>   6.446020000e+05 <=   6.571380483e+05   1.9% (69; 2)
+   231: >>>>>   6.563920000e+05 <=   6.569231603e+05 < 0.1% (87; 35)
+   241: mip =   6.563920000e+05 <=     tree is empty   0.0% (0; 213)
INTEGER OPTIMAL SOLUTION FOUND
Time used:   0.0 secs
Memory used: 0.2 Mb (231419 bytes)
Writing MIP solution to 'C:\Users\CASSIA~1\AppData\Local\Temp\tmpb6ikms_5.glpk.raw'...
256 lines were written
Solution is feasible and optimal
Objective function value =  656392.0
In [22]:
#Impressão da variável Y - Variável de decisão: 1 se o projeto i é selecionado para investimento

for i in model.set_I:
    if pyo.value(Y[i]) > 1.E-3:
        print(f'Y[{i}] = {round(pyo.value(Y[i]),0)}')
Y[0] = 1.0
Y[3] = 1.0
Y[5] = 1.0
Y[6] = 1.0
Y[9] = 1.0
Y[11] = 1.0
Y[12] = 1.0
Y[13] = 1.0
Y[14] = 1.0
Y[15] = 1.0
Y[16] = 1.0
Y[19] = 1.0
Y[20] = 1.0
Y[22] = 1.0
Y[26] = 1.0
Y[27] = 1.0
Y[29] = 1.0
Y[30] = 1.0
Y[31] = 1.0
Y[34] = 1.0
Y[35] = 1.0
Y[38] = 1.0
Y[39] = 1.0
In [23]:
# Lista construída iterativamente, que se tornará o DataFrame final de solução
df_sol_Y = []


for i in model.set_I:
    if pyo.value(Y[i]) > 1.E-3:

        # Valor da variável
        #valor = round(X[i][j][t],2)

        # Linha do DataFrame
        dict_linha = {

                    'Projeto': i ,
                        }

        # Guardando valor
        df_sol_Y.append(dict_linha)

# Criando DataFrame
df_sol_Y = pd.DataFrame(df_sol_Y)
df_sol_Y = df_sol_Y.sort_values(['Projeto'])

df_sol_Y.index = list(range(len(df_sol_Y)))


print(df_sol_Y)
    Projeto
0         0
1         3
2         5
3         6
4         9
5        11
6        12
7        13
8        14
9        15
10       16
11       19
12       20
13       22
14       26
15       27
16       29
17       30
18       31
19       34
20       35
21       38
22       39
In [24]:
#Criação do vetor com os nomes dos projetos


# Inicializa a matriz com zeros
nome_i = [0 for e in dict_I.keys()]

# Preenche as posições de acordo com df_carteira_investimentos
for linha in df_carteira_investimentos.iterrows():
    
    # Extrai o conteúdo da linha atual
    dados_linha = list(linha[1])
    #print(dados_linha)


    # Define o índice do projeto de investimento
    try:
        # Procura o índice na lista do projeto de investimento
        i = list(dict_I.keys())[list(dict_I.values()).index(dados_linha[0])]  
        nome_i[i]= dados_linha[1]        
    except:   
        # Projeto de investimento não encontrado
        i = -1


print(nome_i)
['MASTER 5500 D - PADRÃO - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA - PADRÃO - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15 - PADRÃO - BRA', 'MASTER 5500 D C/ DIRECIONADOR - PADRÃO - BRA', 'MASTER 7500 D - PADRÃO - BRA', 'MASTER 7500 D C/ ESTEIRA PRECISA - PADRÃO - BRA', 'MASTER 7500 D C/ PNEU 11L15 - PADRÃO - BRA', 'MASTER 7500 D C/ ESTEIRA PRECISA C/ PNEU 11L15 - PADRÃO - BRA', 'MASTER 2500 D - PADRÃO - BRA', 'MASTER 2500 D C/ ESTEIRA PRECISA - PADRÃO - BRA', 'MASTER 2500 D CAFEEIRA C/ ESTEIRA PRECISA - PADRÃO - BRA', 'MASTER 2500 D CAFEEIRA C/ ESTEIRA PRECISA C/ DIRECIONADOR - PADRÃO - BRA', 'MASTER 5500 D - VERMELHO - BRA', 'MASTER 5500 D - VERDE - BRA', 'MASTER 5500 D - AMARELO - BRA', 'MASTER 5500 D - AZUL - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA - VERMELHO - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA - VERDE - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA - AMARELO - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA - AZUL - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15 - VERMELHO - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15 - VERDE - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15 - AMARELO - BRA', 'MASTER 5500 D C/ ESTEIRA PRECISA C/ PNEU 11L15 - AZUL - BRA', 'MASTER 5500 D C/ DIRECIONADOR - VERMELHO - BRA', 'MASTER 5500 D C/ DIRECIONADOR - VERDE - BRA', 'MASTER 5500 D C/ DIRECIONADOR - AMARELO - BRA', 'MASTER 5500 D C/ DIRECIONADOR - AZUL - BRA', 'MASTER 7500 D - VERMELHO - BRA', 'MASTER 7500 D - VERDE - BRA', 'MASTER 7500 D - AMARELO - BRA', 'MASTER 7500 D - AZUL - BRA', 'MASTER 7500 D C/ ESTEIRA PRECISA - VERMELHO - BRA', 'MASTER 7500 D C/ ESTEIRA PRECISA - VERDE - BRA', 'MASTER 7500 D C/ ESTEIRA PRECISA - AMARELO - BRA', 'MASTER 7500 D C/ ESTEIRA PRECISA - AZUL - BRA', 'MASTER 7500 D C/ PNEU 11L15 - VERMELHO - BRA', 'MASTER 7500 D C/ PNEU 11L15 - VERDE - BRA', 'MASTER 7500 D C/ PNEU 11L15 - AMARELO - BRA', 'MASTER 7500 D C/ PNEU 11L15 - AZUL - BRA']
In [25]:
#Manipulando DataFrame sol_Y para a construção de gráficos



#Adicionando as colunas de custo do projeto, vpl do projeto e descrição do projeto

# Coluna com os custos de cada projeto 
custo_projeto = []

# Coluna com o vpl de cada projeto
vpl_projeto = []

# Coluna com o nome de cada projeto
nome_projeto = []

# Preenche as posições de acordo com df_sol_X
for linha in df_sol_Y.iterrows():   
    # Extrai o conteúdo da linha atual
    dados_linha = list(linha[1])
    #print(dados_linha)
    custo_projeto.append(c_i[dados_linha[0]])
    vpl_projeto.append(vpl_i[dados_linha[0]])
    nome_projeto.append(nome_i[dados_linha[0]])

# Adicionanado a coluna com os custos de cada projeto no Dataframe da solução
df_sol_Y["Custo realizado"] = [elemento for elemento in custo_projeto]

# Adicionanado a coluna com o VPL de cada projeto no Dataframe da solução
df_sol_Y["VPL realizado"] = [elemento for elemento in vpl_projeto]

# Adicionanado a coluna com os nomes de cada projeto no Dataframe da solução
df_sol_Y["Nome do Projeto"] = [elemento for elemento in nome_projeto]

# Cálculo do total investido
total_investido = np.sum(custo_projeto)

print(total_investido)

# Calculo do VPL total esperado
vpl_total = np.sum(vpl_projeto)

print(vpl_total)
299316
656392
In [26]:
#Criando gráfico dos custos totais de investimento

fig_custo_projeto = px.bar(df_sol_Y, x="Nome do Projeto", y="Custo realizado", text = "Custo realizado", height=1100, width = 1300, color = "Nome do Projeto",title="Custos dos investimentos realizados nos projetos")


# Total investido
#fig_custo_projeto.add_trace(go.Scatter(x=df_sol_Y["Nome do Projeto"], y=[total_investido for nome in df_sol_Y["Nome do Projeto"] ],
                    #line=dict(color='royalblue', width=2, dash='dot'),
                    #name='Custo total investido'))
    
# Budget
#fig_custo_projeto.add_trace(go.Scatter(x=df_sol_Y["Nome do Projeto"], y=[M for nome in df_sol_Y["Nome do Projeto"] ],
                    #line = dict(color='firebrick', width=2, dash='dot'),
                    #name='Budget para investimento'))



fig_custo_projeto.show()
In [27]:
#Criando gráfico dos VPLS totais de investimento




fig_vpl_total = px.pie(df_sol_Y, values='VPL realizado', 
                names='Nome do Projeto', title="VPL dos projetos")

fig_vpl_total.show()



fig_analise_vpl = px.bar(df_sol_Y, x="Nome do Projeto", y="VPL realizado", text = "VPL realizado", height=1100, width = 1300, color = "Nome do Projeto",title="VPL dos projetos")

# Total investido
#fig_analise_vpl.add_trace(go.Scatter(x=df_sol_Y["Nome do Projeto"], y=[total_investido for nome in df_sol_Y["Nome do Projeto"] ],
                    #line=dict(color='royalblue', width=2, dash='dot'),
                    #name='Custo total investido'))
    
# VPL retornado
#fig_analise_vpl.add_trace(go.Scatter(x=df_sol_Y["Nome do Projeto"], y=[vpl_total for nome in df_sol_Y["Nome do Projeto"] ],
                    #line = dict(color='firebrick', width=2, dash='dot'),
                    #name='VPL retornado'))



fig_analise_vpl.show()
In [28]:
dict_final={'Valores': [total_investido,vpl_total], 'Descrição': ['Custo Total', 'VPL Total']}


df_analise_final = pd.DataFrame(data=dict_final)

#rint(df_analise_final)

fig_vpl = px.bar(df_analise_final,  color = 'Descrição')

fig_vpl.show()
In [ ]: